﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.Mvc;
using System.Net.Http;
using WebApi.Models;
using WebApi.Areas.Service.Models;
using System.Text.RegularExpressions;
using System.Text;

namespace WebApi.Controllers
{
    public class HomeController : Controller
    {
        public ActionResult Index()
        {
            return View();
        }

        public ActionResult LoadData()
        {
            using (var client = new HttpClient())
            {
                var cityRequet = client.GetAsync("http://atsoftware.vn:8888/api/sfood/city").Result;
                if (cityRequet.StatusCode == System.Net.HttpStatusCode.OK)
                {
                    CaseData.cityData = cityRequet.Content.ReadAsAsync<ReturnData<List<City>>>().Result.data;
                }
                var districtRequet = client.GetAsync("http://atsoftware.vn:8888/api/sfood/district").Result;
                if (cityRequet.StatusCode == System.Net.HttpStatusCode.OK)
                {
                    CaseData.districtData = districtRequet.Content.ReadAsAsync<ReturnData<List<District>>>().Result.data;
                }
                var categoryRequet = client.GetAsync("http://atsoftware.vn:8888/api/sfood/category").Result;
                if (cityRequet.StatusCode == System.Net.HttpStatusCode.OK)
                {
                    CaseData.categoryData = categoryRequet.Content.ReadAsAsync<ReturnData<List<Category>>>().Result.data;
                }
            }
            return Json(true, JsonRequestBehavior.AllowGet);
        }

        public ActionResult Search()
        {
            CaseData.keyData = new List<Key>();
            return View();
        }

        public ActionResult Suggest(string input, bool enter = false)
        {
            var data = GoiY(input.Trim(), enter);
            if (enter)
            {
                return RedirectToAction("Foods");
            }
            return Json(data, JsonRequestBehavior.AllowGet);
        }

        public ActionResult Foods()
        {
            var data = new ReturnPageData<List<Food>>();
            using (var client = new HttpClient())
            {
                var model = new InputSearchModel()
                {
                    category = "",
                    city = "53a7b2984cd1ac1218b47470",
                    district = "",
                    food = "",
                    page = 1,
                    pagesize = 20,
                    total = 0
                };

                if (CaseData.keyData.FirstOrDefault(x => x.type == 0) != null)//neu co cum tu thanh pho
                {
                    model.city = CaseData.keyData.FirstOrDefault(x => x.type == 0).value;
                }
                if (CaseData.keyData.FirstOrDefault(x => x.type == 1) != null)//neu co quan
                {
                    model.district = CaseData.keyData.FirstOrDefault(x => x.type == 1).value;
                }
                if (CaseData.keyData.FirstOrDefault(x => x.type == 2) != null)//neu co danh muc
                {
                    model.category = CaseData.keyData.FirstOrDefault(x => x.type == 2).value;
                }
                if (CaseData.keyData.FirstOrDefault(x => x.type == 3) != null)//neu co món ăn
                {
                    model.food = CaseData.keyData.FirstOrDefault(x => x.type == 3).value;
                }

                var cityRequet = client.GetAsync("http://atsoftware.vn:8888/api/sfood/SearchFood?city=" + model.city + "&district=" + model.district + "&food=" + model.food + "&category=" + model.category + "&page=" + model.page + "&pagesize=" + model.pagesize + "&total=" + model.total).Result;
                if (cityRequet.StatusCode == System.Net.HttpStatusCode.OK)
                {
                    data = cityRequet.Content.ReadAsAsync<ReturnPageData<List<Food>>>().Result;
                }
                return Json(data, JsonRequestBehavior.AllowGet);
            }
        }

        private List<string> GoiY(string input, bool enter = false)
        {
            List<string> goiy = new List<string>();

            List<string> subggest_City = new List<string>();
            List<string> subggest_District = new List<string>();
            //List<string> subggest_Category =new List<string>();
            List<string> subggest_Food = new List<string>();

            if (input.Length >= 2 )
            {
                //tu nhap vao phai lon hon 2 ky tu
                int size = 0;//danh dau vi tri nhan dang cum tu cuoi cung
                if (CaseData.keyData.Count > 0)
                {
                    size = CaseData.keyData.Max(x => x.endIndex);//set vi tri 
                }

                if (input.Length > size)
                {
                    //tach du lieu nhap moi ra khoi du lieu da dinh nghia
                    string chuoi = input.Substring(size);

                    //gợi ý theo từ chưa được định nghĩa
                    goiy.AddRange(GoiYTinh(chuoi, 5));
                    if (goiy.Count < 5)
                    {
                        goiy.AddRange(GoiYHuyen(chuoi, 5 - goiy.Count));
                    }
                    if (goiy.Count < 5)
                    {
                        goiy.AddRange(GoiYMonAn(chuoi, 5 - goiy.Count));
                    }
                    //nếu có giợi ý thì kết thúc
                    if (goiy.Count > 0)
                    {
                        if (enter)
                        {
                            //kiem tra goi y theo từ cuối cùng
                            subggest_City = GoiYTinh(chuoi, 1, true);
                            if (subggest_City.Count == 0)
                            {
                                subggest_District = GoiYHuyen(chuoi, 1, true);
                                if (subggest_District.Count == 0)
                                {
                                    //chac chan la goi y mon an
                                    //lưu lại nhận biết của cụm từ
                                    CaseData.keyData.Add(new Key
                                    {
                                        text = chuoi,
                                        type = 3,
                                        endIndex = input.Length,
                                        value = chuoi
                                    });
                                }
                                else
                                {
                                    //lưu lại nhận biết của cụm từ
                                    CaseData.keyData.Add(new Key
                                    {
                                        text = chuoi,
                                        type = 1,
                                        endIndex = input.Length,
                                        value = subggest_District[0]
                                    });
                                }
                            }
                            else
                            {
                                //lưu lại nhận biết của cụm từ
                                CaseData.keyData.Add(new Key
                                {
                                    text = chuoi,
                                    type = 0,
                                    endIndex = input.Length,
                                    value = subggest_City[0]
                                });
                            }
                        }
                        return goiy;
                    }

                    //nếu không có gợi ý thì cần phân tích các cụm từ                    
                    //kiem tra cụm từ này có bao nhiêu dấu space
                    List<int> indexSpace = getIndexSpace(chuoi);

                    int type = 0;//lưu viết loại cụm từ đã được nhận biết
                    string text = "";//lưu vết cụm từ đã được nhận biết
                    string value = "";//lưu giá trị cụm từ đã được nhận biết

                    string tam;//cụm từ sử lý
                    for (int i = 0; i < indexSpace.Count; i++)
                    {
                        goiy = new List<string>();//refesh dữ liệu                        
                        tam = chuoi.Substring(0, indexSpace[i]);//cắt cụm từ theo từng vị trí space
                        if (string.IsNullOrEmpty(tam))
                        {
                            continue;
                        }
                        //kiem tra goi y theo dữ liệu tam
                        subggest_City = GoiYTinh(tam, 1, true);
                        if (subggest_City.Count == 0)
                        {
                            subggest_District = GoiYHuyen(tam, 1, true);
                            if (subggest_District.Count == 0)
                            {
                                subggest_Food = GoiYMonAn(tam, 1);
                                goiy.AddRange(subggest_Food);
                            }
                            else
                            {
                                goiy.AddRange(subggest_District);
                            }
                        }
                        else
                        {
                            goiy.AddRange(subggest_City);
                        }
                        if (goiy.Count > 0)//neu co gợi ý
                        {
                            //lưu lại thông tin cụm từ đã được nhận biết
                            text = tam;
                            if (subggest_City.Count > 0)
                            {
                                type = 0;
                                value = subggest_City[0];
                            }
                            else if (subggest_District.Count > 0)
                            {
                                type = 1;
                                value = subggest_District[0];
                            }
                            else
                            {
                                type = 3;
                                value = tam;
                            }

                            if (i == indexSpace.Count - 1)
                            {
                                //lưu lại nhận biết của cụm từ trước
                                CaseData.keyData.Add(new Key
                                {
                                    text = text,
                                    type = type,
                                    endIndex = size + text.Length + 1,//+ ca khoảng trống
                                    value = value
                                });
                                //goi lai goi y
                                return GoiY(input, enter);
                            }
                            continue;//co dữ liệu thì tiếp tục ghép với cụm từ tiếp theo                            
                        }
                        else
                        {
                            //neu ngay cụm từ đầu tiên mà không có gợi ý thì nghỉ luôn
                            if (i == 0)
                            {
                                return goiy;
                            }
                            //lưu lại nhận biết của cụm từ trước
                            CaseData.keyData.Add(new Key
                            {
                                text = text,
                                type = type,
                                endIndex = size + text.Length + 1,//+ ca khoảng trống
                                value = value
                            });
                            //goi lai goi y
                            return GoiY(input, enter);
                        }
                    }
                }
                else
                {
                    //neu xoa chu
                    CaseData.keyData.Remove(CaseData.keyData.LastOrDefault());
                    return GoiY(input, enter);
                }
            }
            return goiy;
        }

        private List<string> GoiYTinh(string input, int top = 5, bool value = false)
        {
            List<string> goiy = new List<string>();
            if (!CaseData.keyData.Any(x => x.type == 0))
            {
                input = ConvertToUnSign(input.Trim().ToLower());
                if (value)
                {
                    //return id
                    goiy.AddRange(CaseData.cityData.Where(x => x.key.Contains(input)).Select(x => x.Id).Take(top).ToList());
                }
                else
                {
                    //return text
                    goiy.AddRange(CaseData.cityData.Where(x => x.key.Contains(input)).Select(x => x.name).Take(top).ToList());
                }
            }
            return goiy;
        }

        private List<string> GoiYHuyen(string input, int top = 5, bool value = false)
        {
            List<string> goiy = new List<string>();
            if (!CaseData.keyData.Any(x => x.type == 1))
            {
                input = ConvertToUnSign(input.Trim().ToLower());
                if (value)
                {
                    //return id
                    goiy.AddRange(CaseData.districtData.Where(x => x.key.Contains(input)).Take(top).Select(x => x.Id).ToList());
                }
                else
                {
                    //return text
                    goiy.AddRange(CaseData.districtData.Where(x => x.key.Contains(input)).Take(top).Select(x => x.name).ToList());
                }
            }
            return goiy;
        }

        private List<string> GoiYDanhMuc(string input)
        {
            List<string> goiy = new List<string>();
            if (!CaseData.keyData.Any(x => x.type == 2))
            {
                input = ConvertToUnSign(input.Trim().ToLower());
                var data = CaseData.categoryData.Where(x => x.key.Contains(input)).Take(5).Select(x => x.key).ToList();
                goiy.AddRange(data);
            }
            return goiy;
        }

        private List<string> GoiYMonAn(string input, int top = 5)
        {
            List<string> goiy = new List<string>();
            if (!CaseData.keyData.Any(x => x.type == 3))
            {
                input = ConvertToUnSign(input.Trim().ToLower());
                using (var client = new HttpClient())
                {
                    string ThanhPho = "53a7b2984cd1ac1218b47470";
                    string quan = "";
                    string danhmuc = "";
                    if (CaseData.keyData.FirstOrDefault(x => x.type == 0) != null)//neu co cum tu thanh pho
                    {
                        ThanhPho = CaseData.keyData.FirstOrDefault(x => x.type == 0).value;
                    }
                    if (CaseData.keyData.FirstOrDefault(x => x.type == 1) != null)//neu co quan
                    {
                        quan = CaseData.keyData.FirstOrDefault(x => x.type == 1).value;
                    }
                    if (CaseData.keyData.FirstOrDefault(x => x.type == 2) != null)//neu co danh muc
                    {
                        danhmuc = CaseData.keyData.FirstOrDefault(x => x.type == 2).value;
                    }

                    var cityRequet = client.GetAsync("http://atsoftware.vn:8888/api/sfood/suggestFood?city=" + ThanhPho + "&district=" + quan + "&food=" + input).Result;
                    if (cityRequet.StatusCode == System.Net.HttpStatusCode.OK)
                    {
                        goiy.AddRange(cityRequet.Content.ReadAsAsync<ReturnData<List<string>>>().Result.data);
                    }

                }
            }
            return goiy;
        }        

        private string ConvertToUnSign(string s)
        {
            Regex regex = new Regex("\\p{IsCombiningDiacriticalMarks}+");
            string temp = s.Normalize(NormalizationForm.FormD);
            return regex.Replace(temp, String.Empty).Replace('\u0111', 'd').Replace('\u0110', 'D');
        }

        private List<int> getIndexSpace(string input)
        {
            List<int> data = new List<int>();
            int vt = 0;
            do
            {
                vt = input.IndexOf(' ', vt + 1);
                if (vt != -1)
                {
                    data.Add(vt);
                }
            } while (vt != -1);
            return data;
        }
    }
}
